package com.yanggeng.demo.beginnerguidedemo.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Shader;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.yanggeng.demo.beginnerguidedemo.TestApplication;
import com.yanggeng.demo.beginnerguidedemo.bean.ConsumeMonthBean;
import com.yanggeng.demo.beginnerguidedemo.bean.Coordinate;
import com.yanggeng.demo.beginnerguidedemo.utils.DateUtils;
import com.yanggeng.demo.beginnerguidedemo.utils.DeviceParams;

import java.util.ArrayList;
import java.util.List;

/**
 * 油耗记录折线图
 * Created by yanggeng on 2017/11/20.
 */

public class OilConsumeLineChartView extends View {

    private int lineStartColor = Color.parseColor("#80FFE132"); // 折线起始颜色

    private int lineEndColor = Color.parseColor("#2DF0DB"); // 折线结束颜色

    private int shadowStartColor = Color.parseColor("#33E1CC67"); // 阴影起始颜色

    private int shadowEndColor = Color.parseColor("#3330ECD5"); // 阴影结束颜色

    private int xAxisColor = Color.parseColor("#EAEFF4"); // 横坐标轴颜色

    private int backgroundLineColor = Color.parseColor("#E0F0FF"); // 背景线条颜色

    private int axisTextColor = Color.parseColor("#637C95"); // 坐标轴文字颜色

    private int[] shadowColors = {shadowStartColor, shadowEndColor};

    private int[] lineColors = {lineStartColor, lineEndColor};

    private int backgroundLineWeight; // 背景线条粗细

    private int lineWeight; // 折线粗细

    private int dotColor = Color.parseColor("#3CD37B"); // 坐标点颜色

    private float dotRadius; // 坐标点半径

    private int xDotColor = Color.parseColor("#4C75DCA3"); // 横坐标点外圈颜色

    private float xDotRadius; // 横坐标点半径

    private float textSize; // 文字大小

    private float width, height;

    private int maxYValue; // 纵坐标轴最大值

    private int minYValue; // 纵坐标轴最小值

    private int dataSize; // 数据个数

    private int yAxisCount; // 纵坐标点个数

    private int yAverageValueSpace; // 纵坐标轴值间隔

    private float yAverageSpace; // 纵坐标轴每份长度

    private float xAverageSpace; // 横坐标轴每份长度

    private float chartHeight; // 折线图高度

    private Paint axisPaint;

    private Paint axisTextPaint;

    private Paint linePaint;

    private Paint xDotStokePaint;

    private Paint xDotSolidPaint;

    private Paint dotPaint;

    private Paint shadowPaint;

    private Path shadowPath;

    private Path linePath;

    private Context context;

    private String[] yAxisValues = {"0", "4", "8", "12", "16", "20"}; // 纵坐标轴值

    private String[] xAxisValues;

    private List<ConsumeMonthBean> data1, data2, data3, data4;

    private List<ConsumeMonthBean> data = new ArrayList<>();

    private String notice = "加油记录少，无法计算百公里油耗"; // 只有1条数据时的提示

    private List<Coordinate> dots = new ArrayList<>();

    private DashPathEffect pathEffect;


    private float selectX = -1, selectY = -1;
    private ConsumeMonthBean selectData;

    public OilConsumeLineChartView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        this.context = context;
        backgroundLineWeight = DeviceParams.dip2px(context, 0.5f);
        lineWeight = DeviceParams.dip2px(context, 1f);
        dotRadius = DeviceParams.dip2px(context, 3f);
        xDotRadius = DeviceParams.dip2px(context, 6f);
        textSize = DeviceParams.sp2px(context, 12f);

        maxYValue = 20;
        minYValue = 0;

        axisPaint = new Paint();

        axisTextPaint = new Paint();
        axisTextPaint.setTextSize(textSize);
        axisTextPaint.setTypeface(TestApplication.TYPEFACE_NUMBER);
        axisTextPaint.setColor(axisTextColor);

        linePaint = new Paint();
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(lineWeight);
        linePaint.setAntiAlias(true);

        xDotStokePaint = new Paint();
        xDotStokePaint.setStrokeWidth(lineWeight);
        xDotStokePaint.setColor(xDotColor);
        xDotStokePaint.setStyle(Paint.Style.STROKE);

        xDotSolidPaint = new Paint();
        xDotSolidPaint.setColor(Color.WHITE);
        xDotSolidPaint.setStyle(Paint.Style.FILL);

        shadowPaint = new Paint();
        shadowPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//        shadowPaint.setColor(shadowEndColor);

        dotPaint = new Paint();
        dotPaint.setColor(dotColor);
        dotPaint.setStyle(Paint.Style.FILL);

        xAxisValues = DateUtils.getLast5Month();

        shadowPath = new Path();

        linePath = new Path();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        yAxisCount = 6;
        yAverageSpace = height / (yAxisCount + 1);
        xAverageSpace = width / 10;
        chartHeight = yAverageSpace * (yAxisCount - 1);
        setMeasuredDimension((int) width, (int) height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        canvas.drawRect(0, 0, width, height, paint);

        drawAxis(canvas);

        drawSelectItem(canvas);
    }

    private void drawAxis(Canvas canvas) {
        // 绘制横坐标轴、背景线和纵坐标轴文字
        axisPaint.setStrokeWidth(backgroundLineWeight);
        axisPaint.setColor(backgroundLineColor);
        axisTextPaint.setTextAlign(Paint.Align.LEFT);
        for (int i = 0; i < yAxisCount; i++) {
            if (i == yAxisCount - 1) {
                axisPaint.setStrokeWidth(lineWeight);
                axisPaint.setColor(xAxisColor);
                canvas.drawLine(xAverageSpace, yAverageSpace * yAxisCount, width - xAverageSpace, yAverageSpace * yAxisCount, axisPaint);
            } else {
                canvas.drawLine(xAverageSpace, yAverageSpace * (i + 1), width - xAverageSpace, yAverageSpace * (i + 1), axisPaint);
            }
            canvas.drawText(yAxisValues[i], xAverageSpace / 2 - 10, yAverageSpace * (yAxisCount - i) + 10, axisTextPaint);
        }

        drawLine(canvas);

        // 绘制横坐标轴坐标点和横坐标轴文字
        axisTextPaint.setTextAlign(Paint.Align.CENTER);
        for (int j = 0; j < xAxisValues.length; j++) {
            canvas.drawCircle(xAverageSpace * (2 * j + 1), yAverageSpace * yAxisCount, xDotRadius, xDotStokePaint);
            canvas.drawCircle(xAverageSpace * (2 * j + 1), yAverageSpace * yAxisCount, xDotRadius - lineWeight, xDotSolidPaint);
            canvas.drawText(xAxisValues[j], xAverageSpace * (2 * j + 1), yAverageSpace * yAxisCount + yAverageSpace / 2 + 10, axisTextPaint);
        }
    }

    private void drawLine(Canvas canvas) {

        if (data.size() == 1) {
            Paint noticePaint = new Paint();
            noticePaint.setColor(Color.parseColor("#898989"));
            noticePaint.setTextSize(DeviceParams.sp2px(context, 14f));
            canvas.drawText(notice, width / 2, yAverageSpace * 3 - DeviceParams.sp2px(context, 14f) / 2, noticePaint);
        } else {
            shadowPath.reset();
            linePath.reset();
            dots.clear();
            for (int i = 0; i < data.size(); i++) {
                float x = 0, y = 0;
                ConsumeMonthBean temp = data.get(i);
                String date = temp.getDate();
                float amount = Float.valueOf(temp.getAmount());
                y = yAverageSpace + chartHeight * (1 - amount / (maxYValue - minYValue));
                for (int j = 0; j < xAxisValues.length - 1; j++) {
                    if (date.contains(xAxisValues[j])) {
                        int day = Integer.valueOf(date.substring(8, 10));
                        x = day / 31f * xAverageSpace * 2 + xAverageSpace * (2 * j + 1);
                    }
                }
                if (i == 0) {
                    shadowPath.moveTo(xAverageSpace, yAverageSpace + chartHeight);
                    shadowPath.lineTo(xAverageSpace, y);
                    linePath.moveTo(xAverageSpace, y);
                }
                linePath.lineTo(x, y);
                shadowPath.lineTo(x, y);
                if (i == data.size() - 1) {
                    shadowPath.lineTo(xAverageSpace * 9, y);
                    shadowPath.lineTo(xAverageSpace * 9, yAverageSpace + chartHeight);
                    shadowPath.close();
                    linePath.lineTo(xAverageSpace * 9, y);
                }
                dots.add(new Coordinate(x, y));
            }
            //  渐变阴影
            Shader mShader = new LinearGradient(xAverageSpace, 0, xAverageSpace * 9, 0, shadowColors, null, Shader.TileMode.CLAMP);
            shadowPaint.setShader(mShader);

            shadowPath.setFillType(Path.FillType.EVEN_ODD);
            canvas.drawPath(shadowPath, shadowPaint); //绘制阴影

            PathMeasure pathMeasure = new PathMeasure(linePath, false);
            float pathLength = pathMeasure.getLength();
            pathEffect = new DashPathEffect(new float[]{pathLength, pathLength}, 1);
            linePaint.setPathEffect(pathEffect);
            // 渐变线条
            Shader mLineShader = new LinearGradient(xAverageSpace, 0, xAverageSpace * 9, 0, lineColors, null, Shader.TileMode.CLAMP);
            linePaint.setShader(mLineShader);
            canvas.drawPath(linePath, linePaint);

            for (int i = 0; i < dots.size(); i++) {
                Coordinate temp = dots.get(i);
                canvas.drawCircle(temp.x, temp.y, dotRadius, dotPaint);
            }
        }

    }

    private void drawSelectItem(Canvas canvas) {
        if (selectX != -1 && selectData != null) {
            axisTextPaint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText(selectData.getAmount(), selectX, selectY - textSize, axisTextPaint);
            canvas.drawText(selectData.getDate().substring(5, 10), selectX, selectY - textSize * 2 - 5, axisTextPaint);
        }
    }

    public void setData(List<ConsumeMonthBean> data) {
        if (data == null || data.size() <= 0) {
            return;
        }
        this.data.clear();
        this.data.addAll(data);
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean resume = false;
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (selectX != -1 || selectY != -1) {
                    selectX = -1;
                    selectY = -1;
                    invalidate();
                }
                if (data.size() > 0 && dots.size() > 0 ) {
                    for (int i = 0; i < dots.size(); i ++) {
                        Coordinate coordinate = dots.get(i);
                        if (x > coordinate.x - dotRadius && x < coordinate.x + dotRadius) {
                            selectX = coordinate.x;
                            selectY = coordinate.y;
                            selectData = data.get(i);
                            invalidate();
                            return true;
                        }
                    }
                }
                break;
        }
        return false;
    }
}
